from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login
from django.contrib.auth import logout
from django.contrib import messages
from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth.forms import UserCreationForm
from django.views.decorators.csrf import csrf_exempt
from django.http import JsonResponse, HttpResponseBadRequest
import json
from urllib import request as urlrequest
from urllib.error import URLError, HTTPError
from urllib.parse import urljoin
from django.contrib.auth import get_user_model
import logging
from django.conf import settings
from django.core.files.storage import FileSystemStorage
from pathlib import Path
import os

# Mock backend base URL for proxying /api/request
MOCK_BACKEND_BASE = "http://127.0.0.1:8080"
def login_view(request):
    if request.method == 'POST':
        form = AuthenticationForm(request, data=request.POST)
        if form.is_valid():
            username = form.cleaned_data.get('username')
            password = form.cleaned_data.get('password')
            user = authenticate(username=username, password=password)
            if user is not None:
                login(request, user)
                messages.success(request, f'欢迎回来, {username}!')
                return redirect('profile')  # 登录成功后重定向到个人主页
            else:
                messages.error(request, '用户名或密码错误,请重试')
        else:
            messages.error(request, '用户名或密码错误,nm')
    else:
        form = AuthenticationForm()
    
    return render(request, 'accounts/login.html', {'form': form})
def register_view(request):
    if request.method == 'POST':
        form = UserCreationForm(request.POST)
        if form.is_valid():
            user = form.save()
            login(request, user)  # 注册后自动登录
            messages.success(request, f'账号创建成功！欢迎, {user.username}!')
            return redirect('profile')  # 注册后进入个人主页
        else:
            # 显示表单错误
            for field, errors in form.errors.items():
                for error in errors:
                    messages.error(request, f'{error}')
    else:
        form = UserCreationForm()
    
    return render(request, 'accounts/register.html', {'form': form})
def logout_view(request):
    logout(request)
    return redirect('login')  # 注销后重定向到登录页面
def home(request):
    return render(request, 'home/home.html')
def discover_view(request):
    return render(request, 'accounts/discover.html')


def profile_view(request):
    """个人主页：上传视频URL、查看关注、收藏、点赞等入口。"""
    if not request.user.is_authenticated:
        return redirect('login')
    return render(request, 'accounts/profile.html', {
        'username': request.user.username,
    })


@csrf_exempt
def api_request_proxy(request):
    """
    代理 /api/request 到本地 mock 后端，保持前端以相对路径 POST JSON。
    - 接受 JSON 请求体
    - 转发到 http://127.0.0.1:8080/api/request
    - 直接返回对方响应
    """
    if request.method != 'POST':
        return HttpResponseBadRequest('Only POST JSON is supported')

    try:
        payload = json.loads(request.body.decode('utf-8') or '{}')
    except Exception:
        return JsonResponse({'insert_success': False, 'error': 'invalid_json'}, status=400)

    target_url = urljoin(MOCK_BACKEND_BASE, '/api/request')
    try:
        logging.info('[api_request_proxy] forwarding to %s payload=%s', target_url, json.dumps(payload, ensure_ascii=False))
    except Exception:
        pass
    data_bytes = json.dumps(payload, ensure_ascii=False).encode('utf-8')

    req = urlrequest.Request(
        target_url,
        data=data_bytes,
        headers={
            'Content-Type': 'application/json; charset=utf-8',
        },
        method='POST'
    )
    try:
        with urlrequest.urlopen(req, timeout=10) as resp:
            body = resp.read()
            status = resp.getcode() or 200
            # 直接透传 JSON
            try:
                out = json.loads(body.decode('utf-8')) if body else {}
            except Exception:
                out = {'insert_success': False, 'error': 'upstream_non_json'}
                status = 502
            try:
                logging.info('[api_request_proxy] upstream status=%s body=%s', status, json.dumps(out, ensure_ascii=False))
            except Exception:
                pass
            return JsonResponse(out, status=status, safe=False)
    except HTTPError as e:
        try:
            err_body = e.read().decode('utf-8')
            out = json.loads(err_body)
        except Exception:
            out = {'insert_success': False, 'error': f'upstream_http_{e.code}'}
        try:
            logging.exception('[api_request_proxy] HTTPError from upstream: %s', e)
        except Exception:
            pass
        return JsonResponse(out, status=e.code)
    except URLError:
        try:
            logging.exception('[api_request_proxy] URLError: upstream_unreachable')
        except Exception:
            pass
        return JsonResponse({'insert_success': False, 'error': 'upstream_unreachable'}, status=502)


@csrf_exempt
def session_login(request):
    """
    在前端已通过 /api/request 验证用户名/密码后，调用该接口以建立 Django 登录会话。
    请求体: { "username": "xxx" }
    如果用户不存在则自动创建一个本地用户（设置为不可用密码）。
    仅用于联调/演示，生产环境请改为真正的认证流程。
    """
    if request.method != 'POST':
        return HttpResponseBadRequest('Only POST JSON is supported')
    try:
        payload = json.loads(request.body.decode('utf-8') or '{}')
        username = (payload.get('username') or '').strip()
    except Exception:
        return JsonResponse({'ok': False, 'error': 'invalid_json'}, status=400)
    if not username:
        return JsonResponse({'ok': False, 'error': 'missing_username'}, status=400)

    User = get_user_model()
    user, created = User.objects.get_or_create(username=username)
    if created:
        user.set_unusable_password()
        user.save()
    login(request, user)
    return JsonResponse({'ok': True, 'username': username})


@csrf_exempt
def upload_video_file(request):
    """
    接收本地视频文件上传，保存到 MEDIA_ROOT/videos 下并返回可访问的本地 URL。
    - 方法: POST multipart/form-data
    - 字段: file (必填)
    返回: { ok: true, url: "/media/videos/<name>", name: "<name>" }
    """
    if request.method != 'POST':
        return HttpResponseBadRequest('Only POST is supported')

    f = request.FILES.get('file')
    if not f:
        return JsonResponse({'ok': False, 'error': 'missing_file'}, status=400)

    # 简单的类型限制
    allowed_ext = {'.mp4', '.webm', '.ogg', '.mov', '.m4v'}
    ext = Path(f.name).suffix.lower()
    if ext not in allowed_ext:
        return JsonResponse({'ok': False, 'error': 'unsupported_format', 'allowed': sorted(allowed_ext)}, status=400)

    # 保存到 MEDIA_ROOT/videos 下
    videos_dir = Path(settings.MEDIA_ROOT) / 'videos'
    videos_dir.mkdir(parents=True, exist_ok=True)
    storage = FileSystemStorage(location=str(videos_dir), base_url=str(settings.MEDIA_URL + 'videos/'))

    # 防止重名：FileSystemStorage 会自动在同名时添加后缀
    saved_name = storage.save(f.name, f)
    url = storage.url(saved_name)

    return JsonResponse({'ok': True, 'url': url, 'name': saved_name})


@csrf_exempt
def delete_video_file(request):
    """
    删除保存于 MEDIA_ROOT/videos 下的本地视频文件。
    - 方法: POST application/json
    - 请求体: { "url": "/media/videos/<name>" } 或 { "name": "<name>" }
    仅允许删除位于 MEDIA_ROOT/videos 子目录下的文件，防止任意路径删除。

    返回: { ok: true, deleted: true/false, name: "<name>" }
    """
    if request.method != 'POST':
        return HttpResponseBadRequest('Only POST JSON is supported')

    try:
        payload = json.loads(request.body.decode('utf-8') or '{}')
    except Exception:
        return JsonResponse({'ok': False, 'error': 'invalid_json'}, status=400)

    url_or_none = (payload.get('url') or '').strip()
    name = (payload.get('name') or '').strip()

    base_url_prefix = str(settings.MEDIA_URL + 'videos/')
    if url_or_none and url_or_none.startswith(base_url_prefix):
        name = url_or_none[len(base_url_prefix):]
    if not name:
        return JsonResponse({'ok': False, 'error': 'missing_name_or_url'}, status=400)

    videos_dir = Path(settings.MEDIA_ROOT) / 'videos'
    target_path = (videos_dir / name).resolve()

    # 安全检查：确保目标在 videos_dir 内部
    try:
        videos_dir_resolved = videos_dir.resolve()
        if os.path.commonpath([str(target_path), str(videos_dir_resolved)]) != str(videos_dir_resolved):
            return JsonResponse({'ok': False, 'error': 'path_outside_media_videos'}, status=400)
    except Exception:
        return JsonResponse({'ok': False, 'error': 'path_resolution_failed'}, status=400)

    deleted = False
    if target_path.exists() and target_path.is_file():
        try:
            target_path.unlink()
            deleted = True
        except Exception as e:
            return JsonResponse({'ok': False, 'error': 'unlink_failed', 'detail': str(e), 'name': name}, status=500)

    return JsonResponse({'ok': True, 'deleted': deleted, 'name': name})